/*
 * Copyright 2022 The Open Islands Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.openislands.oi.console.command;

import org.openislands.oi.config.idgenerator.NodeIdGenerator;
import org.openislands.oi.console.config.annotation.Command;
import org.openislands.oi.console.config.annotation.CommandGroup;
import org.openislands.oi.constant.Dict;
import org.openislands.oi.util.DirectoryUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.util.UUID;

@SuppressWarnings("unused")
@CommandGroup("init")
public class InitCommand {
    private static final Logger log = LoggerFactory.getLogger(InitCommand.class);

    @Command(value = "nodeId", desc = "init one node id")
    public String initNodeId() {
        String config = System.getProperty(Dict.OI_EXTERNAL_CONFIG);
        File confPath;
        if (config == null || !(confPath = new File(config)).exists()) {
            File projectRootPath = DirectoryUtils.getProjectRootPath().toFile();
            confPath = new File(projectRootPath, "/conf");
            if (!confPath.exists() && !confPath.mkdirs()) {
                return "error: conf directory not exists and mkdir failed!";
            }
        }

        File conf = new File(confPath, "tmp." + Dict.COMMON_CONFIG_FILE);
        File source = new File(confPath, Dict.COMMON_CONFIG_FILE);
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(source)));
             Writer writer = new OutputStreamWriter(new FileOutputStream(conf))) {

            // create node id
            final String uuid = UUID.randomUUID().toString().replace("-", "");
            String nodeId = new NodeIdGenerator().getNodeId();
            log.info("init node id: generate node id: {}", nodeId);

            String readLine, prevLevel = "";
            while ((readLine = reader.readLine()) != null) {
                // modify by prefix
                if (!readLine.startsWith(" ")) {
                    int index;
                    if ((index = readLine.indexOf(":")) != -1) {
                        prevLevel = readLine.substring(0, index);
                    }
                } else if ("node".equals(prevLevel)) {
                    String trim = readLine.trim();
                    // modify by prefix
                    if (trim.startsWith("node_id:")) {
                        readLine = "  node_id: " + nodeId;
                    }
                }

                // write line by line
                writer.write(readLine);
                writer.write("\n");
            }
            // close. release file
            writer.flush();
            writer.close();
            reader.close();

            // backup and rename
            File src = new File(confPath, Dict.COMMON_CONFIG_FILE);
            File backup = new File(confPath, "bak." + Dict.COMMON_CONFIG_FILE);
            if (backup.exists() && !backup.delete())
                throw new RuntimeException("delete backup file failed.");
            if (src.exists() && src.renameTo(backup)) {
                log.info("init node id: backup src file");
            }
            if (conf.renameTo(src)) {
                log.info("init node id: mv to src file");
            } else {
                throw new RuntimeException("rename conf file failed.");
            }
        } catch (Exception e) {
            conf.deleteOnExit();
            log.error(e.getMessage(), e);
            return "error: " + e.getMessage();
        }

        return "init node id success.";
    }
}
